// for...in 适合遍历键值对
// for 适合遍历普通数组

// 新的遍历方式for...of
// 基本用法
const arr = [1, 2, 3, 4];
for (let value of arr) {
    console.log(value);
    if (value > 2) {
        // 可以跳出循环
        break;
    }
}
const s = new Set([1, 2, 3, 4]);
for (let value of s) {
    console.log(value);
}
const m = new Map();
m.set("jack", 123);
m.set("tom", 456);
for (const [key, value] of m) {
    // 遍历map得到的还是一个数组
    // 因为遍历的是一个键值结构,所以拿到是一个数组
    // 可以通过数组结构拿到对应的键值
    console.log(key, value);
    // ["jack", 123]
    // [("tom", 456)];
}

// const obj = {
//     name: "jack",
//     age: 18,
// };
// 为什么不能遍历普通对象呢???
// for (const item of obj) {
//     console.log(item); // TypeError: obj is not iterable
// }

// iterable 可迭代接口
// 实现了统一接口,可以理解为统一的规格标准,
// 之所以那些可以被for...of循环的数据类型,是因为内部实现了iterator这个接口
// for...of循环工作的原理调用next方法就可以实现对内部数据的遍历
const array = [1, 2, 3, 4];
const iterator = array[Symbol.iterator]();
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: 4, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

// 通过以上的了解我们知道了 对象内部没有实现iterator这个接口所以无法遍历
// 那么我们可以给对象内部加上这个接口

// 可迭代接口对象 Iterable
const obj = {
    arr: [1, 2, 3, 4],
    [Symbol.iterator]: function () {
        let index = 0;
        const self = this;
        // 返回一个 迭代器接口(Iterator) 的对象
        return {
            next: function () {
                const result = {
                    value: self.arr[index],
                    done: index++ >= self.arr.length,
                };
                // 迭代结果接口对象 IterationResult
                return result;
            },
        };
    },
};
for (const item of obj) {
    console.log(item);
    // 1
    // 2
    // 3
    // 4
}

// 迭代器设计模式开发一个任务清单应用
const todoS = {
    life: ["吃饭", "睡觉", "敲代码"],
    work: ["喝茶", "吃水果"],
    // each方法遍历对象内两个数组的值,不使用迭代器时
    each: function (callback) {
        const arr = [...this.life, ...this.work];
        for (const item of arr) {
            callback(item);
        }
    },
    // 迭代器设计模式, 使用迭代器
    [Symbol.iterator]: function () {
        const arr = [...this.life, ...this.work];
        let index = 0;
        // 返回一个 迭代器的对象
        return {
            next: function () {
                const result = {
                    value: arr[index],
                    done: index++ >= arr.length,
                };
                return result;
            },
        };
    },
};
// 调用each方法
todoS.each((item) => {
    console.log(item);
});

// 使用for...of
for (let item of todoS) {
    console.log(item);
}
// 迭代器的核心是对外提供统一遍历接口
